﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using X.Infrastructure.Shapes;
using X.Infrastructure.WPF.Extends;
using X.WPF.Controls.Enums;
using X.WPF.Controls.EventArgs.CanvasShapeArgs;
using X.WPF.Controls.EventArgs.DraggableControlArgs;

namespace X.WPF.Controls.CustomControls
{
    /// <summary>
    /// 画布长方形控件
    /// </summary>
    public class CanvasRectangle : CanvasShape
    {
        #region # 字段及构造器

        /// <summary>
        /// 顶点
        /// </summary>
        private PointX _vertex;

        /// <summary>
        /// 静态构造器
        /// </summary>
        static CanvasRectangle()
        {
            //注册依赖属性
            CanvasRectangle.XProperty = DependencyProperty.Register(nameof(CanvasRectangle.X), typeof(double), typeof(CanvasRectangle), new PropertyMetadata(0d, CanvasRectangle.OnXChanged));
            CanvasRectangle.YProperty = DependencyProperty.Register(nameof(CanvasRectangle.Y), typeof(double), typeof(CanvasRectangle), new PropertyMetadata(0d, CanvasRectangle.OnYChanged));

        }

        /// <summary>
        /// 默认构造器
        /// </summary>
        public CanvasRectangle()
            : base(CanvasShapeType.Rectangle)
        {
        }

        #endregion

        #region # 属性

        #region X —— double X

        /// <summary>
        /// X依赖属性
        /// </summary>
        public static DependencyProperty XProperty;

        /// <summary>
        /// X
        /// </summary>
        public double X
        {
            get => (double)base.GetValue(CanvasRectangle.XProperty);
            set => base.SetValue(CanvasRectangle.XProperty, value);
        }

        #endregion

        #region Y —— double Y

        /// <summary>
        /// Y依赖属性
        /// </summary>
        public static DependencyProperty YProperty;

        /// <summary>
        /// Y
        /// </summary>
        public double Y
        {
            get => (double)base.GetValue(CanvasRectangle.YProperty);
            set => base.SetValue(CanvasRectangle.YProperty, value);
        }

        #endregion

        #endregion

        #region # 依赖属性 

        #endregion

        #region # 回调方法

        #region X改变回调方法 —— static void OnXChanged(DependencyObject dependencyObject...
        /// <summary>
        /// X改变回调方法
        /// </summary>
        private static void OnXChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            CanvasRectangle canvasRectangle = (CanvasRectangle)dependencyObject;
            double x = (double)eventArgs.NewValue;

        }
        #endregion

        #region Y改变回调方法 —— static void OnYChanged(DependencyObject dependencyObject...
        /// <summary>
        /// Y改变回调方法
        /// </summary>
        private static void OnYChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            CanvasRectangle canvasRectangle = (CanvasRectangle)dependencyObject;
            double y = (double)eventArgs.NewValue;

        }
        #endregion

        #endregion

        #region # 路由事件


        #endregion

        #region # 事件处理程序

        #region 画布鼠标移动事件 —— void OnCanvasMouseMove(object sender...
        /// <summary>
        /// 画布鼠标移动事件
        /// </summary>
        private void OnCanvasMouseMove(object sender, MouseEventArgs eventArgs)
        {
            if (this._parentCanvas == null)
                return;

            PointX position = eventArgs.GetPosition(this._parentCanvas).ToPointX();
            this.Render(position);
        }
        #endregion

        #region 画布鼠标松开事件 —— void OnCanvasMouseUp(object sender...
        /// <summary>
        /// 画布鼠标松开事件
        /// </summary>
        private void OnCanvasMouseUp(object sender, MouseButtonEventArgs eventArgs)
        {
            if (this._parentCanvas == null)
                return;

            PointX position = eventArgs.GetPosition(this._parentCanvas).ToPointX();
            bool result = this.Render(position);

            this._parentCanvas.MouseMove -= this.OnCanvasMouseMove;
            this._parentCanvas.MouseUp -= this.OnCanvasMouseUp;

            if (result)
            {
                CanvasShapeElementDrawnEventArgs areArgs = new CanvasShapeElementDrawnEventArgs(CanvasShape._ShapeDrawnEvent, this, this);
                this.RaiseEvent(areArgs);

                if (!areArgs.IsCancel)
                    return;

                this.DrawCancel();
            }
            else
            {
                this._parentCanvas.Children.Remove(this);
                this.RaiseEvent(new CanvasShapeElementDrawCancelEventArgs(CanvasShape._ShapeDrawCancelEvent, this, this));
            }
        }
        #endregion

        #region 矩形鼠标按下事件 —— void OnRectangleMouseDown(object sender, MouseEventArgs eventArgs)
        /// <summary>
        /// 矩形鼠标按下事件
        /// </summary>
        private void OnRectangleMouseDown(object sender, MouseEventArgs eventArgs)
        {
            // 挂起路由事件
            this.RaiseEvent(new CanvasShapeElementClickEventArgs(CanvasShape._ShapeClickEvent, this, null, this));
        }
        #endregion

        #endregion

        #region # 方法

        // Override

        #region 绘制 —— override void Draw(PointX startPoint)
        /// <summary>
        /// 绘制
        /// </summary>
        /// <param name="startPoint">起点</param>
        public override void Draw(PointX startPoint)
        {
            if (this._parentCanvas == null)
                return;

            this._parentCanvas.MouseMove += this.OnCanvasMouseMove;
            this._parentCanvas.MouseUp += this.OnCanvasMouseUp;
            this._vertex = startPoint;
        }
        #endregion

        #region 绘制 —— override void Draw(double scale, ShapeX shapeX)
        /// <summary>
        /// 绘制
        /// </summary>
        public override void Draw(double scale, ShapeX shapeX)
        {
            RectangleX rectangleX = (RectangleX)shapeX;

            double x = rectangleX.X * scale;
            double y = rectangleX.Y * scale;
            double w = rectangleX.Width * scale;
            double h = rectangleX.Height * scale;
            double x1 = x + w;
            double x2 = y + h;

            this.Name = rectangleX.Name;
            this.Tag = rectangleX.Tag;
            this._vertex = new PointX(x, y);

            this.Render(new PointX(x1, x2));
        }
        #endregion

        #region 拖拽 —— override void Drag(DraggedEventArgs draggedEventArgs)
        /// <summary>
        /// 拖拽
        /// </summary> 
        /// <param name="draggedEventArgs">拖拽参数</param>
        public override void Drag(DraggedEventArgs draggedEventArgs)
        {
        }
        #endregion

        #region 初始化形状控件 —— void InitShapeElement()
        /// <summary>
        /// 初始化形状控件
        /// </summary>
        protected override Shape InitShapeElement()
        {
            Rectangle rectangle = new Rectangle();
            rectangle.MouseDown += this.OnRectangleMouseDown;

            // 绑定宽
            Binding widthBinding = new Binding(nameof(this.Width))
            {
                Source = this,
                Mode = BindingMode.TwoWay
            };
            rectangle.SetBinding(Shape.WidthProperty, widthBinding);
            rectangle.SetValue(Shape.WidthProperty, this.Width);

            // 绑定高
            Binding heightBinding = new Binding(nameof(this.Height))
            {
                Source = this,
                Mode = BindingMode.TwoWay
            };
            rectangle.SetBinding(Shape.HeightProperty, heightBinding);
            rectangle.SetValue(Shape.HeightProperty, this.Height);

            // 绑定X
            Binding xBinding = new Binding(nameof(this.X))
            {
                Source = this,
                Mode = BindingMode.TwoWay
            };
            rectangle.SetBinding(Canvas.LeftProperty, xBinding);

            // 绑定Y
            Binding yBinding = new Binding(nameof(this.Y))
            {
                Source = this,
                Mode = BindingMode.TwoWay
            };
            rectangle.SetBinding(Canvas.TopProperty, yBinding);

            return rectangle;
        }
        #endregion


        // Private

        #region 渲染 —— bool Render(PointX position)
        /// <summary>
        /// 渲染
        /// </summary>
        /// <param name="position">位置</param>
        private bool Render(PointX position)
        {
            // 设置大小
            double width = Math.Abs(position.X - this._vertex.X);
            double height = Math.Abs(position.Y - this._vertex.Y);

            //if (width <= 10 && height <= 10)
            //    return false;

            if (!this._parentCanvas.Children.Contains(this.ShapeElement))
            {

                this._parentCanvas.Children.Add(this.ShapeElement);

                if (!string.IsNullOrWhiteSpace(this.Text))
                {

                    TextBlock textBlock = new TextBlock
                    {
                        Text = this.Text,
                        FontSize = this.FontSize,
                        Padding = new Thickness(5),
                        Margin = new Thickness(1),
                        Background = this.Stroke,
                        Foreground = new SolidColorBrush(Colors.White)
                    };

                    // 绑定X
                    Binding xBinding = new Binding(nameof(this.X))
                    {
                        Source = this,
                        Mode = BindingMode.TwoWay
                    };
                    textBlock.SetBinding(Canvas.LeftProperty, xBinding);

                    // 绑定Y
                    Binding yBinding = new Binding(nameof(this.Y))
                    {
                        Source = this,
                        Mode = BindingMode.TwoWay
                    };
                    textBlock.SetBinding(Canvas.TopProperty, yBinding);

                    this._parentCanvas.Children.Add(textBlock);
                }
            }

            this.Width = width;
            this.Height = height;

            // 设置位置
            if (position.X > this._vertex.X && position.Y > this._vertex.Y)
            {
                this.X = this._vertex.X;
                this.Y = this._vertex.Y;
            }
            if (position.X > this._vertex.X && position.Y < this._vertex.Y)
            {
                this.X = this._vertex.X;
                this.Y = position.Y;
            }
            if (position.X < this._vertex.X && position.Y > this._vertex.Y)
            {
                this.X = position.X;
                this.Y = this._vertex.Y;
            }
            if (position.X < this._vertex.X && position.Y < this._vertex.Y)
            {
                this.X = position.X;
                this.Y = position.Y;
            }

            Panel.SetZIndex(this.ShapeElement, this.ZIndex);

            return true;
        }
        #endregion

        #endregion

    }
}